<?php

namespace App\Http\Controllers\App\V1;

use App\Http\Controllers\ApiController;
use App\Http\Requests\App\V1\ThirdPartyLogin\ThirdPartyLoginStoreRequest;
use App\Models\OpenWechat\WechatUser;
use App\Services\OAuth\UserThirdPartyService;
use App\Services\OpenWechat\Mock;
use App\Services\Utils\Guard;
use Laravel\Socialite\Facades\Socialite;

class ThirdPartyLoginController extends ApiController
{
    const ROUTES = [
        'create'  => 'app.v1.ThirdPartyLogin.create',
        'store'   => 'app.v1.ThirdPartyLogin.store',
        'destroy' => 'app.v1.ThirdPartyLogin.destroy',
    ];

    /**
     * app端，返回第三方登录的配置信息。
     *
     * @return array|\Illuminate\Http\Response
     */
    public function create()
    {
        $third_party_login = [
            [
                "type"   => UserThirdPartyService::OAUTH_TYPE_WECHAT,
                "app_id" => config('services.weixin.client_id'),
            ],
            [
                "type"   => UserThirdPartyService::OAUTH_TYPE_ALIPAY,
                "app_id" => config('services.alipay.app_id'),
            ],
        ];

        return $this->response(compact('third_party_login'));
    }

    /**
     * app端，返回签名：infoStr
     *
     * @return array|\Illuminate\Http\Response
     */
    public function generateAliPaySign()
    {
        $sign = (new AliPayService)->getAppSign();

        return $this->response(compact('sign'));
    }

    /**
     * 第三方登录，app端，根据code获取登录用户的信息。
     *
     * @param ThirdPartyLoginStoreRequest $request
     *
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(ThirdPartyLoginStoreRequest $request)
    {
        switch($request->type)
        {
            case UserThirdPartyService::OAUTH_TYPE_WECHAT:
                $oauth_user = $this->bindWechatUser();
                break;

            case UserThirdPartyService::OAUTH_TYPE_ALIPAY:
                $oauth_user = $this->bindAliPayUser();
                break;

            default:
                $this->checkIsTrue(false, trans('checker.app.login.illegal_oauth_type'));
                return null;
        }

        $user = $oauth_user->user;
        $token = $user ? Guard::JWTUserLogin($user) : null;

        $hathor_mall_api = 'http://hm-api.panxsoft.com/api/v1/app/customer/third-party/hathor-sign';
        $user_json = json_encode($user);
        $post_data = array(
            "user" => $user_json
        );
        $ch = \curl_init();
        \curl_setopt($ch, CURLOPT_URL, $hathor_mall_api);
        \curl_setopt($ch, CURLOPT_POST, 1);
        \curl_setopt($ch, CURLOPT_HEADER, 0);
        // \curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
        \curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        // \curl_setopt($ch,CURLOPT_HTTPHEADER,$header_data);
        \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = \curl_exec($ch);
        \curl_close($ch);
        $code = json_decode($output)->code;
        $mall_token=0;
        if($code == 0){
            $mall_token=json_decode($output)->jwt_token;
        }


        return $this->response(compact('user', 'oauth_user', 'token', 'mall_token'));
    }

    /**
     * @throws \Exception
     */
    private function bindWechatUser(): WechatUser
    {
        try {
            /** @var \SocialiteProviders\Weixin\Provider $socialite_provider */
            $socialite_provider = Socialite::driver('weixin');

            /**
             * @var array $user_data
             * @see Mock::appOAuthUser()
             */
            $user_data = $socialite_provider
                ->stateless() // App 授权不需要 state 参数，否则会报错
                ->user()
                ->user;
        } catch (\Exception $e){
            logger($e->getMessage());

            $this->checkIsTrue(false, trans('checker.app.login.wechat_oauth_error'));

            return null;
        }

        $wechat_user = $this->updateOrCreateUser($this->assembleWechatUserData($user_data));

        return $wechat_user;
    }

    /**
     * @param array $user
     *
     * @return array
     */
    private function assembleWechatUserData(array $user)
    {
        $wechat_user_data = [
            'openid'           => $user['openid'],
            'unionid'          => $user['unionid'],
            'nickname'         => $user['nickname'],
            'nickname_unicode' => json_encode($user['nickname']),
            'sex'              => $user['sex'],
            'language'         => $user['language'],
            'city'             => $user['city'],
            'province'         => $user['province'],
            'country'          => $user['country'],
            'headimgurl'       => $user['headimgurl'],
        ];

        return $wechat_user_data;
    }

    private function updateOrCreateUser(array $wechat_data): WechatUser
    {
        /** @var WechatUser $wechat_user */
        $wechat_user = (new WechatUser)->updateOrCreate (
            ['openid' => $wechat_data['openid']], $wechat_data
        );

        return $wechat_user;
    }

    /**
     * 第三方登录账号解绑
     *
     * @param string $oauth_type
     *
     * @return array|\Illuminate\Http\Response|null
     * @throws \App\Exceptions\ApiAbstractException
     */
    public function destroy(string $oauth_type)
    {
        switch ($oauth_type) {
            case UserThirdPartyService::OAUTH_TYPE_WECHAT:
                $unbound = $this->unbindWechatUser();
                break;

            case UserThirdPartyService::OAUTH_TYPE_ALIPAY:
                $unbound = $this->unbindAliPayUser();
                break;

            default:
                $this->checkIsTrue(false, trans('checker.app.login.wechat_oauth_error'));
                return null;
        }

        return $this->response(compact('unbound'));
    }

    private function unbindWechatUser(): bool
    {
        $user = Guard::user();

        return (bool) $user->wechatUser()->update([
            'user_id' => WechatUser::USER_ID_DEFAULT
        ]);
    }

    private function unbindAliPayUser()
    {
        // TODO
    }

    private function bindAliPayUser()
    {
        return; // TODO ali auth
    }
}
